package com.dst.smart.socket;

import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.Vector;

import com.dst.smart.R;
import com.dst.smart.app.HomeFragment;
import com.dst.smart.app.MyApplication;
import com.dst.smart.app.MainActivity;
import com.dst.smart.json.MasterUtils;
import com.dst.smart.model.Master;
import com.dst.smart.socket.info.ISocketCode;
import com.dst.smart.tools.AppTools;

/**
 * Created by Administrator on 2017/6/27.
 */

public class SocketClient {
	public static int isLinkFlag = 0;
	public static int plusNumber = 0;
	private Vector<String> datas = new Vector<String>();
	private final Object sendLock = new Object();
	private Socket socket;
	private OutputStream outStream = null;
	private InputStream inStream = null;
	private Thread conn = null;
	private Thread send = null;
	private Thread timmer = null;
	private Thread rec = null;
	private String hostIP;

	public void setHostIP(String hostIP) {
		this.hostIP = hostIP;
	}

	private int port = -1;
	private int timeout = 3;
	private ICoallBack CoallBack = null;
	private ISocketPacket _packet = null;
	private String RequestHeader = "$$";// 2424
	private String RequestEnding = "@@";// 0D0A

	/**
	 * @param host
	 *            ip地址
	 * @paramport端口号
	 * @param timeOut
	 *            链接超市时间 秒
	 */
	public SocketClient(String host, int port, int timeOut) {
		this.hostIP = host;
		this.port = port;
		this.timeout = timeOut;
		timmer = new Thread(new Timer());
		timmer.start();

	}

	public boolean isConcet() {
		return socket.isConnected();
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	/**
	 * @param设置连接服务器监听
	 */
	public void setOnConnectListener(ICoallBack CoallBack) {
		this.CoallBack = CoallBack;
	}
	// / <summary>
	// / 服务器请求包尾
	// / </summary>
	public final int CONNECTSTART = 0;

	/** 连接成功 **/
	public final int CONNECTSUCCESS = 1;
	/** 连接失败 **/
	public final int CONNECTFAILURE = -1;
	/** 接收消息 **/
	public final int RECEIVEMESSAGE = 2;
	/** 发送消息 **/
	public final int SENDMESSAGE = 3;
	/** 发送成功 **/
	public final int SENDSUCCESS = 4;
	/** 发送失败 **/
	public final int SENDFAILURE = -2;
	/** 断开连接 **/
	public final int DISCONNECT = -5;
	// private final int STATE_CONNECT_WAIT = 5;// 等待连接
	private int state = DISCONNECT;

	/**
	 * @param_packet设置接受消息监听
	 */
	public void setOnReceiveListener(ISocketPacket _packet) {
		this._packet = _packet;
	}

	/**
	 * 打开连接
	 * 
	 * @return boolean
	 */
	public synchronized void Connection() {

		closeConnection();

		state = CONNECTSTART;
		conn = new Thread(new Conn());
		conn.start();
		isLinkFlag = 5;
		plusNumber = 0;
	}

	private class Conn implements Runnable {
		public void run() {
			try {
				try {
					socket = new Socket(hostIP, port);
					socket.setSoTimeout(timeout * 1500);
					state = CONNECTSUCCESS;
				} catch (Exception e) {
					// TODO: handle exception
					state = CONNECTFAILURE;
				}
				if (state == CONNECTSUCCESS) {
					try {
						outStream = socket.getOutputStream();
						inStream = socket.getInputStream();
						outStream.write(0x01);
					} catch (Exception e) {
						e.printStackTrace();
					}
					isLinkFlag = 10;
					plusNumber = 3;
					HomeFragment.setCode("netSend" + AppTools.getCurrentTime()
							+ "\t" + "link success " + isLinkFlag + "_"
							+ plusNumber);
					send = new Thread(new Send());
					rec = new Thread(new Rec());
					send.start();
					rec.start();
					if (CoallBack != null) {
						CoallBack.OnSuccess(socket);
					}
					Log.e("socket", "success_" + AppTools.getCurrentTime());

				}

			} catch (Exception e1) {
				state = CONNECTFAILURE;
				isLinkFlag = 5;
				plusNumber = 0;
				HomeFragment.setCode("netSend" + AppTools.getCurrentTime()
						+ "\t" + "error " + e1.getMessage());
			}
		}
	}

	/**
	 * 关闭连接的输入输出流
	 * 
	 * @author mick.ge
	 */
	public synchronized void closeConnection() {
		try {
			datas.clear();
			sendLock.notify();

			try {
				if (null != socket) {
					socket.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}

			try {
				if (null != outStream) {
					outStream.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}
			try {
				if (null != inStream) {
					inStream.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}

			try {
				if (null != conn && conn.isAlive()) {
					conn.interrupt();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}

			try {
				if (null != send && send.isAlive()) {
					send.interrupt();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}
			try {
				if (null != rec && rec.isAlive()) {
					rec.interrupt();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void SenddData(String msg) {
		synchronized (sendLock) {
			datas.add(RequestHeader + msg +RequestHeader+RequestEnding);
			sendLock.notify();
		}
	}

	private class Send implements Runnable {
		public void run() {
			try {
				while (true) {
					while (datas.size() > 0) {
						try {
							//字节流计算大小
							//包头、包尾
							String result = datas.remove(0);
							if(result!=null) {
								outStream.write(result.getBytes("UTF-8"));
							}
						} catch (Exception e) {
							sendLock.notify();
						}
					}
					synchronized (sendLock) {
						sendLock.wait();
					}
				}
			} catch (Exception e1) {
				e1.printStackTrace();
				if (state == CONNECTSUCCESS) {
					state = CONNECTFAILURE;
				}
				isLinkFlag = 5;
				plusNumber = 0;
				HomeFragment.setCode("netSend" + AppTools.getCurrentTime()
						+ "\t" + "send error " + e1.toString() + isLinkFlag
						+ "_" + plusNumber);
			}

		}
	}



	String SocketBuff = "";
	private class Rec implements Runnable {
		public void run() {
			Log.e("socket", "R_run"+AppTools.getCurrentTime());
			byte[] b = new byte[1024];
			int len = 0;
			while (state==CONNECTSUCCESS) {
				try {
					if (!socket.isClosed()&&socket.isConnected()&&!socket.isInputShutdown()) {
						try {
							len = inStream.read(b);
						}catch (Exception e){
							e.printStackTrace();
							continue;
						}
						if (len > 0) {
							String strBuffer = new String(b, 0, len, "UTF-8");
							strBuffer = SocketBuff + strBuffer;
							SocketBuff = "";
							String[] array = strBuffer.split("\\$\\$");
							if (array.length > 0) {
								for (int i = 0; i < array.length; i++) {
									SocketBuff += array[i];
									if (SocketBuff.length() > 0) {
										if (SocketBuff.startsWith(RequestEnding) && SocketBuff.endsWith(RequestEnding)) {
											String EndCode = SocketBuff.replace(RequestEnding, "").replace(RequestHeader, "");
											if (_packet != null && EndCode != null) {
												_packet.SocketPacket(EndCode);
												SocketBuff = "";
											}
										} else {
											Log.e("DomTao", SocketBuff);
										}
									}
								}
							}
						}
					} else{
						state = DISCONNECT;
						isLinkFlag = 5;
						plusNumber = 0;
						if (CoallBack != null) {
//							CoallBack.OnDisConnect(MyApplication.getInstance().getString(R.string.servicefail));
						}
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					state = DISCONNECT;
					isLinkFlag = 5;
					plusNumber = 0;
				}
			}
		}
	}

	public void Login() {
		Master masterL = MasterUtils.getMaster(MyApplication.getInstance());
		SenddData(ISocketCode.setLogin(masterL.getMn(), masterL.getPw()));
	}

	public void Line() {
		Master msaterName = MasterUtils.getMaster(MainActivity.activity);
		String result = ISocketCode.setLine(msaterName.getMn(),
				msaterName.getPw());
		SenddData(result);
	}

	private class Timer implements Runnable {
		public void run() {
			while (true) {
				try {
					if (isLinkFlag > 0) {
						isLinkFlag--;
						if (plusNumber > 0) {
							plusNumber--;

							if (plusNumber == 0) {
								if (isLinkFlag > 5 && isLinkFlag < 10) {
									HomeFragment.setCode("netSend"
											+ AppTools.getCurrentTime() + "\t"
											+ "login……" + isLinkFlag + "_"
											+ plusNumber);
									Login();

								} else {
									HomeFragment.setCode("netSend"
											+ AppTools.getCurrentTime() + "\t"
											+ "line……" + isLinkFlag + "_"
											+ plusNumber);
									Line();

								}
							}
						}
					} else {
						HomeFragment.setCode("netSend"
								+ AppTools.getCurrentTime() + "\t"
								+ "connection…… " + isLinkFlag + "_"
								+ plusNumber);
						Connection();
					}
					Thread.sleep(1000);

				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}